// #pragma once
// 定义PTP相关数据结构
#include <stdint.h>
#include <signal.h>
// #include <atomic>
#include <string>

// ptp帧的dmac地址
const uint8_t PTP_DMAC[6] = {0x01, 0x80, 0xC2, 0x00, 0x00, 0x0E};

// ptp帧的消息类型
enum PtpMsgType
{
        E_SYNC = 0x0,
        E_PDELAY_REQ = 0x2,
        E_PDELAY_RESP = 0x3,
        E_FOLLOW_UP = 0x8,
        E_PDELAY_RESP_FOLLOW_UP = 0xA,
        E_ANNOUNCE = 0xB,
        E_SIGNAL = 0xC,
        E_NONE = 0xD, // 更改
};

enum PtpMsgLength
{
        PTP_SYNC_LENGTH = 44, // 58
        PTP_PDELAY_REQ_LENGTH = 68,
        PTP_PDELAY_RESP_LENGTH = 54,          // 68
        PTP_PDELAY_RESP_FLLOW_UP_LENGTH = 54, // 68,
        PTP_SIGNAL_LENGTH = 74,
        PTP_FOLLOW_UP_LENGTH = 76, // 90,
        PTP_ANNOUNCE_LENGTH = 90,
};

// 固定值
#define PTP_MINOR_VERSION_PTP 0x0 // minorVersionPtp
#define PTP_VERSION_PTP 0x2       // versionPtp
#define PTP_MAJOR_SDO_ID 0x1
#define PTP_MINOR_SDO_ID 0x00  // MinorSdoId
#define PTP_ETH_TYPE 0x88F7    // ptp帧的一台类型
#define PTP_CONTROL_FIELD 0x00 // controlField

#define PTP_TLV_TYPE 0x3
#define PTP_LENGTH_FIELD 0x1C
#define PTP_ORGANIZATION_ID 0x80C2
#define PTP_ORGANIZATION_SUB_TYPE 0x1

// 以太头长度
#define ETH_HEADER_LEN 14

const uint16_t PTP_UTC_REASONABLE = 0x000c;
const uint16_t PTP_TIMESCALE = 0x0208;
// sync类型
enum PtpFlags
{
        ONE_STEP = 0x0000,
        TOW_STEP = 0x0200,
};

// ptp头
struct PtpHeader
{
        uint8_t dmac[6];
        uint8_t smac[6];
        uint16_t eth_type;
        // 这里为了不转换网络序 转变地址
        uint8_t message_type : 4;
        uint8_t major_sdo_id : 4;
        uint8_t version_ptp : 4;
        uint8_t minor_version_ptp : 4;

        uint16_t message_length;
        uint8_t domain_number;
        uint8_t minor_sdo_id;
        uint16_t flags;
        uint64_t correction_field;
        uint32_t message_type_specific;
        // sourcePortIdentity 共10字节
        uint8_t clock_identify[8]; // 8字节
        uint16_t port_number;      // 2字节
        // sourcePortIdentity
        uint16_t sequence_id;
        uint8_t control_field;
        uint8_t log_message_interval;
} __attribute__((packed));

// Sync报文
struct PtpSync
{
        PtpHeader ptp_header;
        uint8_t padding[10];
} __attribute__((packed));

// follow_up报文
struct PtpFollowUp
{
        PtpHeader ptp_header;
        uint8_t precise_origin_timestamp[10];
        uint16_t tlv_type;
        uint16_t length_field;
        uint8_t orgainzation_id[3];
        uint8_t organization_sub_type[3];
        int32_t cumulative_scaled_rate_offset;
        uint16_t gm_time_base_indicator;
        uint8_t last_gm_phase_change[12];
        uint32_t scaled_last_gm_freq_change;
} __attribute__((packed));

// Pdelay_req报文
struct PtpPdelayReq
{
        PtpHeader ptp_header;
        uint8_t padding[20];
} __attribute__((packed));

// Pdelay_resp报文
struct PtpPdelayResp
{
        PtpHeader ptp_header;
        uint8_t request_receipt_timestamp[10]; // 时间类型为字符数组
        uint8_t clock_identify[8];
        uint16_t port_number;
} __attribute__((packed));

// Pdelay_resp_follow_up报文
struct PtpPdelayRespFollowUp
{
        PtpHeader ptp_header;
        uint8_t request_origin_timestamp[10];
        uint8_t clock_identify[8];
        uint16_t port_number;

} __attribute__((packed));

struct PtpPathTraceTLV
{
        uint16_t tlv_type;
        uint16_t length_field;
        uint8_t path_sequence[8];
};

// ptp announce
struct PtpAnnounce
{
        PtpHeader ptp_header;
        uint8_t reserved[10];
        uint16_t current_utc_offset;
        uint8_t reserved1;
        uint8_t gm_priority1;
        uint8_t gm_clock_class;
        uint8_t gm_clock_accuracy;
        uint16_t gm_clock_var;
        uint8_t gm_priority2;
        uint8_t gm_identify[8];
        uint16_t steps_removed;
        uint8_t time_source;
        PtpPathTraceTLV path_trace_tlv;
} __attribute__((packed));

// Pdelay_resp_follow_up报文
struct PtpSignal
{
        PtpHeader ptp_header;
        uint8_t target_port_identify[10];
        uint8_t req_tlv[16];
} __attribute__((packed));

// 链路延时测量相关头文件
enum Port_delay_state
{
        NONE = 0,
        SEND_REQ,            // 发送pdelay_req
        RECV_RESP,           // 收到Pdelay_resp
        RECV_RESP_FOLLOW_UP, // 收到Pdelay_resp_follow_up
        DONE,                // 完成链路延时测量
        NEIGHIBOR_YES,       // 是否完成邻居频比测量，是否有八个时间戳可以上报
};

struct Port_delay
{
        uint16_t local_sequence_id; // 本地报文序列号
        uint16_t ex_sequence_id;    // 外部报文序列号
        uint64_t timestamp_1;       // 链路延时计算时间戳 t1
        uint64_t timestamp_2;       // 链路延时计算时间戳 t2
        uint64_t timestamp_3;       // 链路延时计算时间戳 t3
        uint64_t timestamp_4;       // 链路延时计算时间戳 t4
        uint64_t last_timestamp_1;  // 上一次链路延时计算时间戳 t1
        uint64_t last_timestamp_2;  // 上一次链路延时计算时间戳 t2
        uint64_t last_timestamp_3;  // 上一次链路延时计算时间戳 t3
        uint64_t last_timestamp_4;  // 上一次链路延时计算时间戳 t4
        uint64_t link_delay;        // 链路延时
        double neighbour_rateratio; // 邻居频比
        uint16_t port_number;

        uint64_t timestamp_2_ex; // 对面发过来的req，此时我接收到，更新t2值，写在resp里返回给对面
        uint64_t timestamp_3_ex; // 链路延时计算时间戳 t3
};

struct Init_pack
{
        uint8_t padding[24]; // 正常情况24 测试是16
        PtpHeader ptp_header;
        uint8_t reserve[64]; // 空余64 以防越界
} __attribute__((packed));

// 同步相关头文件
enum Sync_state
{
        RECV_SYNC,      // 接收到sync
        RECV_FOLLOW_UP, // 接收到follow_up
        SYNC_DONE       // 完成同步
};

struct Ptp_Sync
{
        uint64_t t1;          // 发送sync帧时间
        uint64_t t0;          // 接收sync帧时间
        uint16_t sequence_id; // 序列号
        uint32_t offset;      // 偏移值
};

// 定义一个结构体来存储port_identity信息
struct PortIdentity
{
        uint8_t clockIdentity[8];
        int portNumber;
};

// 定义一个结构体来存储TSN配置
struct TSNConfig
{
        int device_id;
        int gm_flag;
        int port_num;
        int master_port;
        int slave_port;
        int link_delay_measure_period;
        int sync_period;
        int domain_number;
        PortIdentity port_identity;
        int mean_link_delay_thrld;
};

// 定义一个sync结构体来存储数据
struct SyncInfo
{
        uint16_t SequenceID;                // （序列号）
        uint64_t PreciseOriginTimestamp;    // 32s + 32ns
        int64_t CorrectionField;            // ns（修正域时间）
        uint64_t RecvTimestamp;             // 接收时刻 // 48s + 32ns
        double GMRateRatio;                 // GM频比
        double NeighborRateRatio;           // 邻居频比
        int64_t CumulativeScaledRateOffset; // 累计放大频差
        double tickLength;                  // 拍长
        int32_t offset;
};

// 定义一个delay结构体来存储数据
struct LinkdelayInfo
{
        uint16_t sequenceid;
        uint16_t PortID;
        uint64_t t1;
        uint64_t t2;
        uint64_t t3;
        uint64_t t4;
        uint64_t last_t1;
        uint64_t last_t2;
        uint64_t last_t3;
        uint64_t last_t4;
        uint64_t Linkdelay;
        double NeighborRateRatio; // 各端口之间的邻居频比
};

// linkdelaymeasure.cpp
uint8_t *sendPdelayReq(uint16_t sequence_id);
uint8_t *sendPdelayResp();
uint8_t *sendPdelayRespFollowUp();
int parsePdelayReq(struct Pack_rec tsmp_pack);
int parsePdelayResp(struct Pack_rec tsmp_pack);
int parsePdelayRespFollowUp(struct Pack_rec tsmp_pack);
int calculateLinkDelay();
int calculateNR();
// 将本节点的GM频率比写进寄存器
int w_register(uint32_t addr);

// timesync.cpp
uint8_t *sendSync(uint16_t sequence_id);
uint8_t *sendFollowUp();
int parseSync(Pack_rec tsmp_pack);
int parseFollowUp(Pack_rec tsmp_pack);
uint32_t int32toReg(int32_t value);
int32_t calculateOffset();
uint32_t calculateticklen();
void printBinary(uint32_t value);

// sync.cpp
//  到时触发发送程序, sig判断类型，后续两个参数无用,发送pdelay
void send_frame_pdelay(int sig, siginfo_t *info, void *context);
// 到时触发发送程序, sig判断类型，后续两个参数无用,发送sync
void send_frame_sync(int sig, siginfo_t *info, void *context);
int timer_fun_sync(int seconds);
int timer_fun_pdelay(int seconds);
int packRec(int gm_flag);

// config.cpp
bool readTSNConfig(std::string &filename, TSNConfig &config);

// init_ptp.cpp
//  初始化PTP头
int init(PtpHeader *ptpheader, PtpMsgType type, uint16_t sequence_id);
uint8_t *e2t(uint64_t t, uint8_t t3[10]);
uint64_t t2e(uint8_t *buffer);
uint32_t extract_seconds(uint64_t timestamp);
uint32_t extract_nanoseconds(uint64_t timestamp);
int init_info_pdelay();
int init_info_sync();

// report_state.cpp
uint64_t ex_time_seconds(uint8_t *buffer);
uint32_t ex_time_nanoseconds(uint8_t *buffer);
void write_to_syncfile(const SyncInfo &syncInfo, const char *filename);
void write_to_delayfile(const LinkdelayInfo &linkInfo, const char *filename);
